#!/usr/bin/python
# Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
# Any live cell with more than three live neighbours dies, as if by overcrowding.
# Any live cell with two or three live neighbours lives on to the next generation.
# Any dead cell with exactly three live neighbours becomes a live cell.
from time import sleep
grid = {}

for x in range(1,21):
    for y in range(1,21):
        grid[(x,y)] = False # sets all the cells to dead

def show_field():
    bookends = ("| " + (" - "*20)+ " |")
    print(bookends)
    for y in range(1,21):
        line = ""
        for x in range(1,21):
            if grid[(x,y)] == True:
                line += " X "
            else:
                line = line + " . "
        print("| " + line + " |")
    print(bookends)

def check_adjacent(cell):
    number = 0 # of adjaenct cells
    for x in range(-1,2):
        for y in range(-1,2):
            if grid.get((cell[0]+x, cell[1]+y)) == True:
                number += 1
    if grid[cell] == True:
        number -= 1 # because we don't want a live cell reporting itself as a neighbor
    return number

def rules():
    global grid
    grid_copy = dict(grid)
    for cell in grid:
        if check_adjacent(cell) < 2 and grid[cell] == True:
            grid_copy[cell] = False
        elif check_adjacent(cell) > 3 and grid[cell] == True:
            grid_copy[cell] = False
        elif check_adjacent(cell) in [2,3] and grid[cell] == True:
            grid_copy[cell] = True
        elif check_adjacent(cell) == 3 and grid[cell] == False:
            grid_copy[cell] = True
    grid = grid_copy

starting_cells = [(10,9), (10,10), (11,9), (11,10), (12,11), (12,12), (13,11), (13,12)] #, (11,10), (9,11), (10,11), (11,11)]

for cell in starting_cells:
    grid[(cell)] = True # True is alive, False is dead

while True:
    show_field()
    rules()
    input()